C++结构体

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  本教程将从 C++ 结构体的特性、定义、使用到进阶技巧,全面拆解 C++ 结构体的核心用法,帮助你掌握这一基础且重要的编程工具。

教程目录导航

一、C++ 结构体的核心概述

1.1 基本定义

C++ 中的结构体(struct)是一种用户自定义复合数据类型,它不仅能封装多个不同类型的成员变量(数据),还能封装操作这些数据的成员函数(行为),是面向对象编程(OOP)中 “封装” 特性的重要载体。

1.2 C++ 结构体与 C 语言结构体的核心区别

特点 C 语言结构体 C++ 结构体
成员类型 仅支持成员变量(数据) 支持成员变量 + 成员函数(数据 + 行为)
访问权限 无访问权限控制(默认公开) 支持public/private/protected(默认public)
面向对象特性 不支持(无构造 / 析构函数) 支持(构造、析构、继承、多态等)
赋值与使用 仅数据拷贝 支持对象赋值、函数调用等完整操作

1.3 C++ 结构体与类(class)的区别

C++ 中struct和class的功能几乎完全一致,唯一核心区别是默认访问权限

除此之外,两者都支持构造函数、析构函数、继承、虚函数等面向对象特性。

二、C++ 结构体的基本使用

2.1 结构体的定义

包含成员变量成员函数

语法格式:


struct 结构体名 {
    // 访问权限修饰符(可选,默认public)
    访问权限(public/private/protected):
        // 成员变量(数据成员)
        数据类型 成员变量1;
        数据类型 成员变量2;
        // ... 更多成员变量
        
        // 成员函数(成员方法,分为声明+实现)
        返回值类型 成员函数名1(参数列表);
        返回值类型 成员函数名2(参数列表);
        // ... 更多成员函数
};

// 结构体成员函数的外部实现(若内部仅声明)
返回值类型 结构体名::成员函数名(参数列表) {
    // 函数体(可访问结构体的成员变量)
}
        

示例:

定义一个描述 “学生” 的结构体(包含成员变量和成员函数)


// 定义Student结构体
struct Student {
    // 成员变量(默认public,可直接访问)
    char name[20];  // 姓名
    int age;        // 年龄
    float score;    // 成绩
    
    // 成员函数:内部直接实现
    void printInfo() {
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
        cout << "成绩:" << score << endl;
    }
    
    // 成员函数:仅声明,外部实现
    void updateScore(float newScore);
    
    // 成员函数:带参数的初始化函数
    void initStudent(const char* stuName, int stuAge, float stuScore) {
        strcpy(name, stuName);
        age = stuAge;
        score = stuScore;
    }
};

// 成员函数的外部实现(必须加"结构体名::"作用域解析符)
void Student::updateScore(float newScore) {
    score = newScore;
    cout << "成绩已更新为:" << newScore << endl;
}
        

2.2 结构体对象的创建与初始化

C++ 支持多种结构体对象(实例)的创建和初始化方式,核心包括直接创建、构造函数初始化等。

方式 1:直接创建对象并手动赋值


int main() {
    // 创建Student对象
    Student stu1;
    
    // 直接访问成员变量赋值(因默认public,可直接修改)
    strcpy(stu1.name, "张三");
    stu1.age = 18;
    stu1.score = 92.5;
    
    // 调用成员函数
    cout << "stu1信息:" << endl;
    stu1.printInfo();
    
    // 更新成绩并再次打印
    stu1.updateScore(95.0);
    cout << "更新后stu1信息:" << endl;
    stu1.printInfo();
    
    return 0;
}
        

方式 2:通过初始化函数批量赋值


int main() {
    Student stu2;
    // 调用自定义初始化函数,批量设置成员变量
    stu2.initStudent("李四", 19, 88.0);
    
    cout << "\nstu2信息:" << endl;
    stu2.printInfo();
    return 0;
}
        

方式 3:构造函数初始化(推荐,C++ 面向对象特性)


// 重新定义带构造函数的Student结构体
struct Student {
    // 成员变量
    char name[20];
    int age;
    float score;
    
    // 无参构造函数(默认构造函数)
    Student() {
        // 初始化默认值
        strcpy(name, "未知姓名");
        age = 0;
        score = 0.0;
        cout << "无参构造函数被调用" << endl;
    }
    
    // 有参构造函数(重载)
    Student(const char* stuName, int stuAge, float stuScore) {
        strcpy(name, stuName);
        age = stuAge;
        score = stuScore;
        cout << "有参构造函数被调用" << endl;
    }
    
    // 成员函数
    void printInfo() {
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
        cout << "成绩:" << score << endl;
    }
    
    void updateScore(float newScore) {
        score = newScore;
        cout << "成绩已更新为:" << newScore << endl;
    }
};

// 测试构造函数
int main() {
    // 调用无参构造函数创建对象
    Student stu3;
    cout << "\nstu3默认信息:" << endl;
    stu3.printInfo();
    
    // 调用有参构造函数创建对象
    Student stu4("王五", 20, 95.0);
    cout << "\nstu4初始化信息:" << endl;
    stu4.printInfo();
    
    return 0;
}
        

2.3 结构体成员的访问方式

根据对象的类型(普通对象 / 指针对象),使用不同的访问运算符:

场景 1:普通对象访问成员(. 成员访问运算符)

语法:对象名.成员变量名 / 对象名.成员函数名(参数)


Student stu;
stu.age = 18;  // 访问成员变量
stu.printInfo();  // 调用成员函数
        

场景 2:指针对象访问成员(-> 成员访问运算符)

语法:对象名.成员变量名 / 对象名.成员函数名(参数)


int main() {
    // 方式1:栈区对象取地址
    Student stu5("赵六", 17, 90.0);
    Student* pStu1 = &stu5;
    
    // 通过指针访问成员
    cout << "\n指针访问stu5信息:" << endl;
    cout << "姓名:" << pStu1->name << endl;
    pStu1->updateScore(92.0);
    pStu1->printInfo();
    
    // 方式2:堆区动态创建对象(new关键字)
    Student* pStu2 = new Student("孙七", 21, 85.5);
    cout << "\n堆区对象pStu2信息:" << endl;
    pStu2->printInfo();
    
    // 释放堆区内存(避免内存泄漏)
    delete pStu2;
    pStu2 = nullptr;  // 避免野指针
    
    return 0;
}
        

三、C++ 结构体的进阶特性

3.1 访问权限控制(public/private/protected)

示例:带访问权限控制的结构体


struct Student {
private:
    // 私有成员变量:外部无法直接访问
    char name[20];
    int age;
    float score;
    
public:
    // 公有成员函数:作为外部访问私有成员的接口
    Student(const char* stuName, int stuAge, float stuScore) {
        strcpy(name, stuName);
        age = stuAge;
        score = stuScore;
    }
    
    void printInfo() {
        // 内部可访问私有成员
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
        cout << "成绩:" << score << endl;
    }
    
    void setAge(int newAge) {
        // 可在函数内添加合法性校验
        if (newAge > 0 && newAge < 100) {
            age = newAge;
            cout << "年龄已更新为:" << newAge << endl;
        } else {
            cout << "无效的年龄值!" << endl;
        }
    }
    
    int getAge() {
        return age;
    }
};

int main() {
    Student stu("周八", 19, 89.0);
    stu.printInfo();
    
    // stu.age = 20;  // 错误:age是私有成员,外部无法直接访问
    stu.setAge(20);  // 正确:通过公有成员函数修改私有成员
    cout << "当前年龄:" << stu.getAge() << endl;
    
    stu.setAge(-5);  // 非法值,会被函数拦截
    return 0;
}

3.2 析构函数:资源自动释放

析构函数是与结构体同名、前缀加~的特殊成员函数,无参数、无返回值,用于对象销毁时自动释放资源(如堆区内存、文件句柄等),仅能有一个(无法重载)。


struct MyString {
    // 成员变量
    char* str;  // 字符指针,指向堆区字符串
    
    // 构造函数:动态分配内存
    MyString(const char* s) {
        int len = strlen(s) + 1;
        str = new char[len];  // 堆区分配内存
        strcpy(str, s);
        cout << "构造函数:分配内存,字符串为:" << str << endl;
    }
    
    // 析构函数:释放堆区内存
    ~MyString() {
        delete[] str;  // 释放数组内存
        str = nullptr;
        cout << "析构函数:释放内存" << endl;
    }
    
    // 成员函数
    void printStr() {
        cout << "字符串内容:" << str << endl;
    }
};

int main() {
    MyString strObj("Hello C++ Struct!");
    strObj.printStr();
    
    // 对象销毁时,析构函数会自动调用,无需手动释放
    return 0;
}

3.3 结构体数组:存储多个对象

结构体数组用于批量存储同类型结构体对象,便于统一管理和遍历。


int main() {
    // 定义结构体数组并通过有参构造函数初始化
    Student stuArr[3] = {
        Student("张三", 18, 92.5),
        Student("李四", 19, 88.0),
        Student("王五", 20, 95.0)
    };
    
    // 遍历结构体数组
    cout << "\n学生列表:" << endl;
    for (int i = 0; i < 3; i++) {
        cout << "\n第" << i+1 << "个学生:" << endl;
        stuArr[i].printInfo();
    }
    
    // 修改数组中对象的属性
    stuArr[1].setAge(21);
    cout << "\n修改后第2个学生年龄:" << stuArr[1].getAge() << endl;
    
    return 0;
}

3.4 结构体作为函数参数 / 返回值

C++ 支持结构体对象作为函数的参数和返回值,推荐使用指针或引用传递(避免对象拷贝的性能开销)。

场景 1:结构体对象作为参数(值传递)


// 值传递:会拷贝整个对象
void printStudent(Student stu) {
    cout << "\n函数内打印学生信息:" << endl;
    stu.printInfo();
}

int main() {
    Student stu("赵六", 17, 90.0);
    printStudent(stu);
    return 0;
}
    

场景 2:结构体指针 / 引用作为参数(高效传递)


// 引用传递:直接操作原对象,无拷贝开销
void updateStudentScore(Student& stu, float newScore) {
    stu.updateScore(newScore);
}

// 指针传递:同样无拷贝开销
void printStudentByPtr(Student* pStu) {
    cout << "\n指针传递打印学生信息:" << endl;
    pStu->printInfo();
}

int main() {
    Student stu("孙七", 21, 85.5);
    updateStudentScore(stu, 89.0);
    printStudentByPtr(&stu);
    return 0;
}
    

场景 3:结构体作为函数返回值


// 返回结构体对象
Student createStudent(const char* name, int age, float score) {
    return Student(name, age, score);
}

int main() {
    Student stu = createStudent("周八", 19, 88.0);
    cout << "\n创建的学生信息:" << endl;
    stu.printInfo();
    return 0;
}
    

四、C++ 结构体的典型应用场景

五、注意事项

六、总结

本教程从 C++ 结构体的特性、定义、使用到进阶技巧,全面拆解 C++ 结构体的核心用法。掌握结构体的运用,是学习数据结构的重要基础之一。


返回顶部